<template>
  <div id="container"></div>
</template>

<script>
import G6 from "@antv/g6";
const mockData = {
  id: "g1",
  name: "我是科目我是科目我是科目我是科目我是科目我是科目目目目目",
  dataType: "root",
  amount: 123123213123.123123,
  children: [
    {
      id: "g12",
      name: "Deal with LONG label LONG label LONG label LONG label",
      amount: 123123213123.123123,
      children: [
        {
          id: "g121",
          name: "Name3",
          collapsed: true,
          amount: 123123213123.123123,
          children: [
            {
              id: "g1211",
              name: "Name4",
              amount: 123123213123.123123,
              children: [],
            },
          ],
        },
        {
          id: "g122",
          name: "Name5",
          collapsed: true,
          amount: 2.34,
          children: [
            {
              id: "g1221",
              name: "Name6",
              amount: 0.123123,
              children: [
                {
                  id: "g12211",
                  name: "Name6-1",
                  amount: 123123,
                  children: [],
                },
              ],
            },
            {
              id: "g1222",
              name: "Name7",
              amount: 123123213123.123123,
              children: [],
            },
          ],
        },
        {
          id: "g123",
          name: "Name8",
          collapsed: true,
          amount: 12,
          children: [
            {
              id: "g1231",
              name: "Name8-1",
              amount: 123123213123.123123,
              children: [],
            },
          ],
        },
      ],
    },
    {
      id: "g13",
      name: "Name9",
      amount: 123123213123.123123,
      children: [
        {
          id: "g131",
          name: "Name10",
          amount: 12313123.123123,
          children: [],
        },
        {
          id: "g132",
          name: "Name11",
          amount: 123123213123.123123,
          children: [],
        },
      ],
    },
    {
      id: "g14",
      name: "Name12",
      amount: 123123213123.123123,
      children: [
      {
          id: "g155521",
          name: "Name3999",
          collapsed: true,
          amount: 123123213123.123123,
          children: [
            {
              id: "g12158821",
              name: "Name4",
              amount: 123123213123.123123,
              children: [],
            },
          ],
        },
        {
          id: "5656",
          name: "Name5",
          collapsed: true,
          amount: 2.34,
          children: [
            {
              id: "g19+66221",
              name: "Name6",
              amount: 0.123123,
              children: [
                {
                  id: "g122754511",
                  name: "Name6-1",
                  amount: 123123,
                  children: [],
                },
              ],
            },
            {
              id: "g1656222",
              name: "Name7",
              amount: 123123213123.123123,
              children: [],
            },
          ],
        },
      ],
    },
  ],
};
export default {
  name: "HelloWorld",
  props: {
    msg: String,
  },
  created() {},
  mounted() {
    this.initAntv();
  },
  methods: {
    // 初始化
    initAntv() {
      //  组件props
      const props = {
        data: mockData,
        config: {
          padding: [20, 50],
          // defaultLevel: 3,
          defaultZoom: 0.8,
          modes: { default: ["zoom-canvas", "drag-canvas"] },
        },
      };

      const container = document.getElementById("container");
      const width = container.scrollWidth;
      const height = container.scrollHeight || 500;

      // 默认配置
      const defaultConfig = {
        width,
        height,
        modes: {
          default: ["zoom-canvas", "drag-canvas"],
        },
        fitView: true,
        animate: true,
        minZoom: 0.5,
        maxZoom: 1.5,
        linkCenter: false,
        defaultNode: {
          // 默认节点
          type: "flow-rect",
        },
        defaultEdge: {
          // 默认边
          type: "cubic-horizontal",
          style: {
            stroke: "rgb(93, 162, 216)",
          },
        },
        layout: {
          // layout 布局配置
          type: "mindmap",
          direction: "V",
          dropCap: false,
          rankSep: 350,
          nodeSep: 100,
          getHeight: () => {
            return 60;
          },
          // 节点横向间距的回调函数
          getHGap: function getHGap() {
            return 150;
          },
        },
      };

      // 自定义节点
      const registerFn = () => {
        /**
         * 自定义节点
         */
        G6.registerNode(
          "flow-rect",
          {
            shapeType: "flow-rect",
            draw(cfg, group) {
              const { name = "", collapsed, dataType, amount } = cfg;

              const config = {
                basicColor: "rgb(66, 151, 215)", // 左边粗线的颜色
                fontColor: "rgb(74, 177, 241)", // 字体颜色
                borderColor: "rgb(169, 217, 252)", // 边框颜色
                bgColor: "rgb(230, 240, 250)", // 矩形背景色
              };

              const rectConfig = {
                width: 243,
                height: 64,
                lineWidth: 1,
                fontSize: 12,
                opacity: 1,
                fill: config.bgColor,
                stroke: config.borderColor,
                radius: 2,
                cursor: "pointer",
              };

              const nodeOrigin = {
                x: -rectConfig.width / 2,
                y: -rectConfig.height / 2,
              };

              const textConfig = {
                textAlign: "left",
                textBaseline: "bottom",
              };

              if (dataType != "root") {
                /* 左边的小圆点 */
                group.addShape("circle", {
                  attrs: {
                    x: nodeOrigin.x - 0,
                    y: 0,
                    r: 6,
                    fill: config.basicColor,
                  },
                  name: "left-dot-shape",
                });
              }
              // 外层矩形
              const rect = group.addShape("rect", {
                attrs: {
                  x: nodeOrigin.x,
                  y: nodeOrigin.y,
                  ...rectConfig,
                },
              });

              /* 左边的粗线 */
              group.addShape("rect", {
                attrs: {
                  x: nodeOrigin.x,
                  y: nodeOrigin.y,
                  width: 3,
                  height: rectConfig.height,
                  fill: config.basicColor,
                  radius: 1.5,
                },
                name: "left-border-shape",
              });

              const rectBBox = rect.getBBox();

              // 科目
              group.addShape("text", {
                attrs: {
                  ...textConfig,
                  x: 12 + nodeOrigin.x,
                  y: 20 + nodeOrigin.y,
                  text: name.length > 16 ? name.substr(0, 16) + "..." : name,
                  fontSize: 12,
                  opacity: 0.85,
                  fill: config.fontColor,
                  cursor: "pointer",
                },
                name: "name-shape",
              });

              if (amount) {
                // 金额-矩形
                const amountRect = group.addShape("rect", {
                  attrs: {
                    fill: "#fff",
                    radius: 2,
                    stroke: config.borderColor,
                    cursor: "pointer", // 需要调整
                  },
                  name: "amount-container-shape",
                });
                // 金额
                const amountText = group.addShape("text", {
                  attrs: {
                    ...textConfig,
                    x: rectBBox.maxX - 10,
                    y: rectBBox.maxY - 10,
                    text: `${amount}`,
                    fontSize: 12,
                    textAlign: "right",
                    fill: "#000",
                  },
                  name: "amount-text-shape",
                });

                const amountBBox = amountText.getBBox(); // 获取元素的包围盒
                /* amountBBox */
                amountRect.attr({
                  x: rectBBox.maxX - amountBBox.width - 15,
                  y: rectBBox.maxY - 27,
                  width: amountBBox.width + 10,
                  height: amountBBox.height + 10,
                });
              }

              // collapse rect
              if (cfg.children && cfg.children.length) {
                group.addShape("circle", {
                  attrs: {
                    x: rectConfig.width / 2 + 8.5,
                    y: 0,
                    r: 8,
                    width: 16,
                    height: 16,
                    stroke: "rgb(74, 177, 241)",
                    cursor: "pointer",
                    fill: "#fff",
                  },
                  name: "collapse-back",
                  modelId: cfg.id,
                });

                // collpase text
                group.addShape("text", {
                  attrs: {
                    x: rectConfig.width / 2 + 8.5,
                    y: 1,
                    textAlign: "center",
                    textBaseline: "middle",
                    text: collapsed ? "+" : "-",
                    fontSize: 16,
                    cursor: "pointer",
                    fill: "rgb(74, 177, 241)",
                  },
                  name: "collapse-text",
                  modelId: cfg.id,
                });
              }
              return rect;
            },
            update(item) {
              // const { level, name } = cfg;
              // console.log("update生命周期函数中的cfg========", cfg)
              const group = item.getContainer();
              let mask = group.find((ele) => ele.get("name") === "mask-shape");
              let maskLabel = group.find(
                (ele) => ele.get("name") === "mask-label-shape"
              );

              group.get("children").forEach((child) => {
                if (child.get("name")?.includes("collapse")) return;
                child.show();
              });
              mask?.animate(
                { opacity: 0 },
                {
                  duration: 200,
                  callback: () => mask.hide(),
                }
              );
              maskLabel?.animate(
                { opacity: 0 },
                {
                  duration: 200,
                  callback: () => maskLabel.hide(),
                }
              );
            },
            setState(name, value, item) {
              if (name === "collapse") {
                const group = item.getContainer();
                const collapseText = group.find(
                  (e) => e.get("name") === "collapse-text"
                );
                if (collapseText) {
                  if (!value) {
                    collapseText.attr({
                      text: "-",
                    });
                  } else {
                    collapseText.attr({
                      text: "+",
                    });
                  }
                }
              }
            },
            getAnchorPoints() {
              return [
                [0, 0.5],
                [1, 0.5],
              ];
            },
          },
          "rect"
        );
      };

      registerFn();

      const { data } = props;
      let graph = null;

      const initGraph = (data) => {
        if (!data) {
          return;
        }
        const { onInit, config } = props;
        const tooltip = new G6.Tooltip({
          // offsetX and offsetY include the padding of the parent container
          offsetX: 20,
          offsetY: 30,
          // 允许出现 tooltip 的 item 类型
          itemTypes: ["node"],
          // custom the tooltip's content
          // 自定义 tooltip 内容
          getContent: (e) => {
            const outDiv = document.createElement("div");
            outDiv.style.textAlign = "left";
            const nodeName = e.item.getModel().name;
            let formatedNodeName = "";
            for (let i = 0; i < nodeName.length; i++) {
              formatedNodeName = `${formatedNodeName}${nodeName[i]}`;
              if (i !== 0 && i % 20 === 0)
                formatedNodeName = `${formatedNodeName}<br/>`;
            }
            outDiv.innerHTML = `${formatedNodeName}`;
            return outDiv;
          },
          shouldBegin: (e) => {
            // if (e.target.get('name') === 'name-shape' || e.target.get('name') === 'mask-label-shape') return true;
            const nodeName = e.item.getModel().name;
            if (nodeName.length > 24) {
              return true;
            } else {
              return false;
            }
          },
        });
        graph = new G6.TreeGraph({
          container: "container",
          ...defaultConfig,
          ...config,
          plugins: [tooltip],
        });
        if (typeof onInit === "function") {
          onInit(graph);
        }
        graph.data(data);
        graph.render();

        const handleCollapse = (e) => {
          const target = e.target;
          const id = target.get("modelId");
          const item = graph.findById(id);
          const nodeModel = item.getModel();
          nodeModel.collapsed = !nodeModel.collapsed;
          graph.layout();
          graph.setItemState(item, "collapse", nodeModel.collapsed);
        };
        graph.on("collapse-text:click", (e) => {
          handleCollapse(e);
        });
        graph.on("collapse-back:click", (e) => {
          handleCollapse(e);
        });
      };

      initGraph(data);

      if (typeof window !== "undefined")
        window.onresize = () => {
          if (!graph || graph.get("destroyed")) return;
          if (!container || !container.scrollWidth || !container.scrollHeight)
            return;
          graph.changeSize(container.scrollWidth, container.scrollHeight);
        };
    },
  },
};
</script>

<!-- Add "scoped" attribute to limit CSS to this component only -->
<style scoped></style>
